import Vue from 'vue'
import $http from '@/api/server/http'
import { Message } from 'element-ui'
import request from '@/utils/request'
import { configuration } from '@/store/global'
import { getOrgs, getUserOrgs } from '@/api/server/user'
import { subject } from '@/registerApps'
import { cloneDeep } from 'lodash'
import { setCompany, getUserInfo } from '@/api/server/user'
import vue from 'vue'

let filters = []
const sysConfig = () => {
  const userInfo = Vue.prototype.$userInfo
  const config = {
    headers: {
      Authorization: 'Bearer ' + userInfo.token,
      clientId: userInfo.clientId,
      realm: userInfo.realm
    }
  }
  return config
}
let microBaseRoute = ''

function tarver(target, arr) {
  const types = [2, 3]
  if (types.includes(target.type)) {
    arr.push(target)
  }
  if (target.child && target.child.length > 0) {
    target.child.map(v => {
      tarver(v, arr)
    })
  }
}

const setMenu = (data, routePath = [], isFirst, menu = [], type) => {
  const reData = []
  data.forEach(item => {
    try {
      // if (item.disabled === false) {
      //   if (item.children && item.children.length) {
      //     const itemData = {
      //       ...item,
      //       children: setMenu(item.children, routePath, false, isFirst ? item.resUrl : baseRoute)[0]
      //     }
      //     throw itemData
      //   } else {
      //     throw item
      //   }
      // }
      if (item.disabled === false) {
        if (item.children && item.children.length) {
          const itemData = {
            ...item,
            children: setMenu(item.children, routePath, false, menu, type)[0]
          }
          throw itemData
        } else {
          const itemData = {
            ...item
          }
          throw itemData
        }
      }
    } catch (item) {
      // item.resUrl = baseRoute ? item.resUrl.indexOf(baseRoute) >= 0 ? item.resUrl : baseRoute + item.resUrl : item.resUrl
      // reData.push(Object.assign(item, { resUrl: microBaseRoute + item.resUrl }))
      // routePath.push(item.resUrl)
      // if (item.children && item.children.length > 0) {
      //   routePath.push(item.resUrl + '/')
      // }
      reData.push(Object.assign(item, { resUrl: item.resUrl }))
      menu.push(Object.assign(item, { resUrl: item.resUrl }))
      routePath.push(item.resUrl.replace(/(.*)\?.*/gi, '$1'))
      routePath.push(item.resUrl.replace(/(.*)\?.*/gi, '$1') + '/')
    }
  })
  return [reData, routePath, menu]
}
const setAuth = (data, authList = []) => {
  data.forEach(item => {
    if (item.resType === 2 && item.disabled === false) {
      authList.push(item.code)
    }
    if (item.children && item.children.length) {
      setAuth(item.children, authList)[0]
    }
  })
  return authList
}

function traverse(target, userOrgs, isAdmin = false) {
  if (target.id !== '' && !isAdmin) {
    if (!userOrgs.find(v => v.id === target.id)) {
      target.disabled = true
      target.isDisabled = true
    }
  }
  if (target.child && target.child.length > 0) {
    let count = 0
    const length = target.child.length
    for (let i = target.child.length - 1; i >= 0; i--) {
      const v = target.child[i]
      if (!filters.includes(v.id) && !isAdmin) {
        target.child.splice(i, 1)
        count++
      } else {
        traverse(v, userOrgs, isAdmin)
      }
    }
    if (count === length) {
      delete target.child
    }
  } else {
    delete target.child
  }
}

const _handleError = message => {
  Message({
    message,
    type: 'error'
  })
  return false
}

const state = {
  queryStatus: 'done',
  manageList: {},
  sysParams: {},
  menuData: [],
  pathList: [],
  authList: [],
  originData: [],
  childCleintId: '',
  projectName: '',
  baseRoute: '',
  basePathlist: [],
  regStatue: false,
  orgs: {}, // 当前公司下的所有组织
  currentCompany: '', // 当前的公司数据
  globalLoading: false, // 全局loading
  copyRight: {},
  rule: {}, // 菜单存放
  isToggle: false, // 是否切换
  userOrgs: [], // 用户拥有的组织
  allMenu: [], // 所有菜单
  hasSetMenu: false, // 第一次进来
  paths: [],
  currentUserOrgs: [],
  currentOrgs: [],
  tiny: true,
  indexOrgs: [],
  messageState: false, // 消息刷新状态
  messageMore: false,
  dashBoardRule: '' // 首页
}

const mutations = {
  QUERY_STATUS: (state, data) => {
    state.queryStatus = data
  },
  SET_PARAMS: (state, data) => {
    state.sysParams = data
  },
  SET_MANAGE: (state, data) => {
    state.manageList[data.code] = data.data
  },
  SET_MENU: (state, list) => {
    state.menuData = list
  },
  SET_PATH_LIST: (state, list) => {
    state.pathList = list
  },
  SET_AUTH_LIST: (state, list) => {
    state.authList = list
  },
  SET_CHILD_CLIENT_ID: (state, clientId) => {
    state.childCleintId = clientId
  },
  SET_PROJECT_NAME: (state, name) => {
    state.projectName = name
  },
  SET_TOP_BANNER: (state, routes) => {
    state.topRoutes = routes
  },
  SET_BASE_ROUTE: (state, route) => {
    microBaseRoute = route
    state.microBaseRoute = route
  },
  SET_BASE_PATH_LIST: (state, basePathlist) => {
    state.basePathlist = basePathlist
  },
  SET_REG_STATUE: (state, regStatue) => {
    state.regStatue = regStatue
  },
  SET_COPY_RIGHT: (state, copyRight) => {
    state.copyRight = copyRight
  },
  SET_ORIGIN_DATA: (state, list) => {
    state.originData = list
  },
  // 设置所有顶层菜单
  SET_RULE: (state, rule) => {
    state.rule = rule
  },
  // 设置全局loading
  SET_GLOBAL_LOADING: (state, globalLoading) => {
    state.globalLoading = globalLoading
  },
  // 设置当前侧边栏完全收缩状态
  SET_TOGGLE: (state, toggle = undefined) => {
    if (toggle !== undefined) {
      state.isToggle = toggle
    } else {
      state.isToggle = !state.isToggle
    }
  },
  // 设置侧边栏部分收缩状态
  SET_TINY: (state, tiny = undefined) => {
    if (tiny !== undefined) {
      state.tiny = tiny
    } else {
      state.tiny = !state.tiny
    }
  },
  // 设置所有菜单
  SET_ALL_MENU: (state, allMenu) => {
    state.allMenu = allMenu
  },
  // 设置当前获取菜单状态
  SET_MENU_STATE: (state, statue) => {
    state.hasSetMenu = statue
  },
  // 设置当前的组织id
  SET_CURRENT_ORG: (state, company) => {
    state.currentCompany = company
  },
  // 设置所有组织
  SET_ORGS: (state, orgs) => {
    state.orgs = orgs
  },
  // 获取当前用户所有公司下的组织quanx
  SET_USER_ORGS: (state, orgs) => {
    state.userOrgs = orgs
  },
  SET_PATHS: (state, paths) => {
    state.paths = paths
  },
  // 获取当前企业下的用户组织权限
  SET_SET_CURRENT_ORGS_USER_ORGS: (state, currentUserOrgs) => {
    state.currentUserOrgs = currentUserOrgs
  },
  // 设置当前企业下的组织
  SET_CURRENT_ORGS: (state, currentOrgs) => {
    state.currentOrgs = currentOrgs
  },
  // 设置指标的企业
  SET_INDEX_ORGS: (state, indexOrgs) => {
    state.indexOrgs = indexOrgs
  },
  SET_MESSAGE_STATE: state => {
    state.messageState = !state.messageState
  },
  SET_MESSAGE_MORE: state => {
    state.messageMore = !state.messageMore
  },
  // iam配置首页页面
  SET_DASHBOARD_RULE: (state, dashBoardRule) => {
    state.dashBoardRule = dashBoardRule
  }
}

const actions = {
  async getEnter({ commit }) {
    try {
      const userInfo = vue.prototype.$userInfo
      const userOrgs = []
      const username = userInfo.userRep.username
      const uOrgs = userInfo.userRep.enterprise
      let base = uOrgs.find(v => v.type === 1)
      let indexCompany = []
      // 如果有本部就搜集本部并且把属于本部下的企业划进去，没有则所有企业平铺
      if (base) {
        const child = (await getOrgs(base.id)).data
        const childCompany = []
        tarver(child, childCompany)
        childCompany.map(v => {
          delete v.child
        })
        base = cloneDeep(base)
        base.child = []
        const baseChild = []
        const otherComp = []
        // 找出同样是公司并且在本部下级的
        uOrgs.map(v => {
          if (v.id !== base.id) {
            // 如果属于本部则本部的permissioncode会和深层企业的permissioncode重合
            v.permissionCode.indexOf(base.permissionCode) >= 0 &&
              !childCompany.find(x => x.id === v.id) &&
              baseChild.push(cloneDeep(v))
            otherComp.push(cloneDeep(v))
          }
        })

        baseChild.map(v => {
          delete v.child
        })
        otherComp.map(v => {
          delete v.child
        })
        base.child = [...baseChild, ...childCompany]
        indexCompany = [base, ...otherComp]
      } else {
        indexCompany = [
          ...uOrgs.map(v => {
            const clone = cloneDeep(v)
            delete clone.child
            return clone
          })
        ]
      }
      let child = []
      // 这一部主要的目的是筛选出没有父节点的元素，也就是第一层元素
      child = uOrgs.filter(v => {
        return !uOrgs.find(x => {
          // 这里indexOf可能在比如 2-2, 2-22-2中失效，所以需要再过滤
          let isTotalEqual = false
          // 首先找到符合筛选条件的
          if (
            v.permissionCode.indexOf(x.permissionCode) === 0 &&
            x.id !== v.id
          ) {
            // 然后判断是否全等
            const arr = v.permissionCode.split('-')
            x.permissionCode.split('-').forEach((z, i) => {
              z === arr[i] && (isTotalEqual = true)
            })
          }
          return isTotalEqual
        })
      })
      const enterprise = {
        id: '',
        name: '全部',
        child: child
      }
      const que2 = []
      enterprise.child.map(v => {
        que2.push(getOrgs(v.id))
      })
      const orgs = await Promise.all(que2)
      enterprise.child.map((v, i) => {
        Object.assign(v, orgs[i].data)
      })

      // 如果是admin用户
      if (username === 'admin') {
        filters = ['']
      } else {
        const auths = userInfo.userRep.organizations

        userInfo.userRep.organizations && userOrgs.push(...auths)

        filters = []
        auths.map(v => {
          filters.push(...v.permissionCode.split('-'))
        })
      }
      filters = Array.from(new Set(filters))
      traverse(enterprise, userOrgs, username === 'admin')
      commit('SET_ORGS', enterprise)
      commit('SET_USER_ORGS', userOrgs)
      commit('SET_INDEX_ORGS', indexCompany)
      subject.next({
        type: 'parent',
        payload: {
          userOrgs,
          orgs: enterprise
        }
      })
    } catch (e) {
      console.log(e)
    }
  },
  async getCompanyOrg({ state, commit, dispatch }) {
    try {
      const orgs = (await getOrgs(state.currentCompany.id)).data
      const userOrgs = (await getUserOrgs(state.currentCompany.id)).data

      commit('SET_CURRENT_ORGS', orgs)
      commit('SET_SET_CURRENT_ORGS_USER_ORGS', userOrgs)
    } catch (e) {
      console.log(e)
      dispatch('getMenu')
    }
  },
  async getMenu({ state, commit }, isFirst) {
    const userInfo = Vue.prototype.$userInfo
    const clientId = userInfo.clientId
    const currentCompany = state.currentCompany
    const config = {
      headers: {
        Authorization: 'Bearer ' + userInfo.token,
        clientId,
        realm: userInfo.realm
      }
    }
    const res = await request.get(
      configuration.baseUrl.keycloakConfig.rootUrl + 'resource/list/menu',
      { params: { clientId, realm: userInfo.realm, active: 0 }, ...config }
    )
    const rule = {}
    let dashBoardRule
    let count = 0
    res.data.map(v => {
      if (!v.smallFront && v.isDisplay === '0' && !v.disabled) {
        count++
        const ret = setMenu(v.children, [], true, [], `${currentCompany.type}`)
        rule[v.resUrl] = {
          children: ret[0].map(v => ({ ...v, isSecond: true })),
          res: v,
          paths: ret[1]
        }
        if (count === 1) {
          dashBoardRule = rule[v.resUrl]
          commit('SET_DASHBOARD_RULE', rule[v.resUrl].children[0].resUrl)
        }
      }
    })
    commit('SET_RULE', rule)
    const menuMsg = setMenu(res.data, [], true, [], `${currentCompany.type}`)
    commit('SET_ALL_MENU', menuMsg[2])
    // 不想在iam上处理太多层，所以/路由由项目添加，在generateRealRoutes方法中已经对/的redirect
    menuMsg[1].push('/')

    if (isFirst) {
      commit('SET_PATH_LIST', menuMsg[1])
      // 需要将除了/之外的activeRule传给子应用
      commit('SET_ORIGIN_DATA', res.data)
      commit('SET_BASE_PATH_LIST', [
        ...menuMsg[1],
        ...menuMsg[1].map(v => `${v}/404`)
      ])
    } else {
      // commit('SET_MENU', menuMsg[0])
      commit('SET_PATH_LIST', menuMsg[1])
    }
    return res
  },
  async setCompany({ commit, dispatch }, company) {
    try {
      commit('SET_CURRENT_ORG', company)
      await setCompany(company.id)
      dispatch('getCompanyOrg')
      const res = await getUserInfo({
        realm: Vue.prototype.$userInfo.realm,
        username: Vue.prototype.$userInfo.userRep.username
      })
      const userInfo = {
        token: Vue.prototype.$userInfo.token,
        realm: Vue.prototype.$userInfo.realm,
        clientId: Vue.prototype.$userInfo.clientId,
        ...res.data
      }
      Vue.prototype.$userInfo = userInfo

      commit('SET_PATH_LIST', [])
    } catch (e) {
      console.log(e)
    }
  },
  async getAuth({ state, commit }, params) {
    const userInfo = Vue.prototype.$userInfo
    const config = sysConfig()
    const res = await request.post(
      configuration.baseUrl.keycloakConfig.rootUrl + 'resource/mylist',
      { clientId: userInfo.clientId },
      config
    )
    const authMsg = setAuth(res.data)
    commit('SET_AUTH_LIST', authMsg)
  },
  getParams({ state, commit }) {
    if (state.sysParams.value || state.sysParams.status === 'pending') {
      return Promise.resolve()
    }
    commit('SET_PARAMS', {
      status: 'pending',
      value: []
    })
    const userInfo = Vue.prototype.$userInfo
    return $http
      .get('sysParams', {
        paraType: '1',
        page: 1,
        pageSize: 20,
        active: '0',
        realm: userInfo.realm,
        clientId: userInfo.clientId
      })
      .then(res => {
        if (res.data.code !== 0) {
          commit('SET_PARAMS', {
            status: res.status,
            value: []
          })
          throw Error('接口返回数据不对')
        }
        commit('SET_PARAMS', {
          status: res.status,
          value: res.data.data.objList
        })
        return res.data.data
      })
      .catch(err => {
        commit('SET_PARAMS', {
          status: err.response.status,
          value: []
        })
        throw err
      })
  },
  setManage({ commit, state }, params) {
    if (state.manageList[params.code] && state.manageList[params.code].length) {
      return Promise.resolve()
    }
    commit('SET_MANAGE', { code: params.code, data: params.data })
  },
  // 判断权限
  hasAuth({ commit, state }, params) {
    const config = sysConfig()
    return $http.post('userAuth', params, { ...config }).then(res => {
      return res.data.code
    })
  },
  getManage({ state, commit }, params) {
    const roleId = state.sysParams.value.find(
      item => item.paraName === params.name
    ).paraValue
    const config = sysConfig()
    return $http
      .get('userByRole', {
        ...config,
        params: { roleId: roleId, searchInfo: params.wd }
      })
      .then(res => {
        if (res.data.code !== 0) {
          return _handleError(res.data.resultMsg)
        }
        commit('SET_MANAGE', { code: params.code, data: res.data.data })
        return res
      })
  }
}

export default {
  namespaced: true,
  state,
  mutations,
  actions
}
